﻿using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using LRJ.Profile;
using LRJ.Text;

namespace LRJ.Snipplr
{
    /// <summary>
    /// Snippet object that read, write, and delete snippets
    /// to Snipplr.  Extends the API Snippet sturct with more
    /// robust types methods.
    /// </summary>
    public class Snippet
    {
        private SnippetListModel m_list;
        private SnippetModel m_snippet;
        
        private bool _public = true;

        public string Id
        {
            get { return m_list.id; }
        }
        public bool Favorite
        {
            get { return m_list.favorite; }
        }
        public DateTime Update
        {
            get { return m_list.updated.datetime; }
        }
        public string UserId
        {
            get { return m_snippet.user_id; }
        }
        public string Username
        {
            get { return m_snippet.username; }
        }
        public string Title
        {
            get { return m_snippet.title; }
            set { m_snippet.title = value; }
        }
        public string Language
        {
            get { return m_snippet.language; }
            set { m_snippet.language = value; }
        }
        public string Code
        {
            get { return m_snippet.source; }
            set { m_snippet.source = value; }
        }
        public string Comment
        {
            get { return m_snippet.comment; }
            set { m_snippet.comment = value; }
        }
        public string[] Tags
        {
            get { return m_snippet.tags.Trim().Split(' '); }
            set { m_snippet.tags = string.Join(" ", value); }
        }
        public DateTime Created
        {
            get { return DateTime.Parse(m_snippet.created); }
        }
        public string SnipplrUrl
        {
            get { return m_snippet.snipplr_url; }
        }
        public bool Public
        {
            get { return _public; }
        }

        public Snippet()
        {
        }       
        
        /// <summary>
        /// Posts a new snippet to Snippler.
        /// </summary>
        /// <param name="api_key">Required. The API key of the Snipplr user to which 
        /// the snippet will belong. An error message will be returned if the API 
        /// key is invalid.</param>
        /// <param name="title">Required. The title of the snippet.</param>
        /// <param name="code">Required. The snippet’s source code.</param>
        /// <param name="tags">Optional. A space delimited list of keywords to tag 
        /// the snippet with.</param>
        /// <param name="language">Optional. The language to mark the snippet as. 
        /// Use the language name found in Snipplr’s URLs. For example, “javascript” or “c-plus-plus”.</param>
        /// <returns>bool</returns>
        public static bool Post(string apiKey, string title, string code, string tags, string language)
        {
            try
            {
                SnipplrProxy.Create().PostSnippet(apiKey, title, code, tags, language);
                return true;
            }
            catch (CookComputing.XmlRpc.XmlRpcFaultException)
            {
                return false;
            }
        }
        /// <summary>
        /// Posts the current snippet to Snippler by the current snippets model.
        /// </summary>
        /// <param name="apiKey"></param>
        /// <returns></returns>
        public bool Put(string apiKey)
        {
            try
            {
                SnipplrProxy.Create()
                    .PostSnippet(apiKey, m_snippet.title, m_snippet.source, m_snippet.tags, m_snippet.language);
                return true;
            }
            catch (CookComputing.XmlRpc.XmlRpcFaultException)
            {
                return false;
            }

        }
        /// <summary>
        /// Delete Snippet from Snipplr by Id
        /// </summary>
        /// <param name="apiKey">User api key for Snipplr</param>
        /// <param name="snippetId">Required. The ID of the snippet to fetch.</param>
        /// <returns></returns>
        public bool Delete(string apiKey, string snippetId)
        {
            try
            {
                SnipplrProxy.Create().DeleteSnippet(apiKey, snippetId);
                return true;
            }
            catch (CookComputing.XmlRpc.XmlRpcFaultException)
            {
                return false;
            }
        }
        
        /// <summary>
        /// Gets a service model snippet from Snipplr by ID
        /// </summary>
        /// <param name="snippetId">Required. The ID of the snippet to fetch.</param>
        /// <returns>SnippetModel</returns>
        public void Get(string snippetId)
        {
            try
            {
                m_snippet = SnipplrProxy.Create().GetSnippet(snippetId);
            }
            catch (CookComputing.XmlRpc.XmlRpcFaultException ex)
            {
                throw(IdNotFoundException)ex;
            }
        }
        /// <summary>
        /// Loads the current snippet from Snippler by the current snippets id.
        /// </summary>
        public void Get()
        {
            this.Get(m_snippet.id);

        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class SnippetList : List<SnippetListModel>
    {
        public enum Sort
        {
            Title,
            Date,
            Random,
        }
        public SnippetList(string apiKey, string tags, Sort sort, int limit)
        {

            this.Get(apiKey, tags, sort.ToString().ToLower(), limit);
        }
        /// <summary>
        /// Returns an XML formatted list of snippets matching the specified criteria.
        /// </summary>
        /// <param name="api_key">Required. The API key of the Snipplr user. 
        /// Snipplr returns all of this user’s snippets. An error message 
        /// will be returned if the API key is invalid.</param>
        /// <param name="tags">Optional. A space delimited list of tags (keywords)
        /// to filter the results by. Snipplr returns snippets which contain at 
        /// least one of the keywords in the snippet’s title or that match one 
        /// of the snippet’s tags.</param>
        /// <param name="sort">Optional. Can be one of these three values: 
        /// “title”, “date”, “random”.</param>
        /// <param name="limit">Optional. The number of snippets to return.</param>
        /// <returns>Only returns snippets owned by the user or marked as favorites
        /// of the user. It does not search all of the snippets on Snipplr.
        /// </returns>
        public void Get(string apiKey, string tags, string sort, int limit)
        {
            SnippetListModel[] m_list = SnipplrProxy.Create().ListSnippets(apiKey, tags, sort, limit);
            try
            {
                m_list = SnipplrProxy.Create().ListSnippets(apiKey, tags, sort, limit);
            }
            catch (APIServiceFaultException ex)
            {
                switch (ex.ErrorStatus)
                {
                    case APIServiceStatusCode.BadApiKey:
                        throw (BadApiKeyException)ex;
                    case APIServiceStatusCode.ListNotFound:
                        throw (ListNotFoundException)ex;
                }
            }            
            for (int i = 0; i <= m_list.Length - 1; i++)
            {
                this.Add(m_list[i]);
            }
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class Languages : List<SnippetLangList>
    {
        public Languages() { this.Get(); }
        public void Get()
        {
            SnippetLangList[] m_list = SnipplrProxy.Create().ListLanguages();
            for (int i = 0; i <= m_list.Length - 1; i++)
            {
                this.Add(m_list[i]);
            }
        }
    }
    #region SnipplrExceptions

    public class SnipplrException : APIServiceFaultException  { SnipplrException() : base(){} }
    public class ListNotFoundException : SnipplrException { }
    public class IdNotFoundException : SnipplrException { }
    public class BadApiKeyException : SnipplrException { }
    public class MethodNotFoundException : SnipplrException { }

    #endregion
}